package com.scau402.system1.listener;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.scau402.system1.domain.dto.StopCheckDTO;
import com.scau402.system1.domain.dto.WmsStopCheckDTO;
import com.scau402.system1.domain.po.WmsCheckBoundOrderPO;
import com.scau402.system1.domain.po.WmsCheckboundJadeDetailPO;
import com.scau402.system1.mapper.IWmsCheckboundJadeDetailMapper;
import com.scau402.system1.mapper.IWmsCheckboundOrderMapper;
import com.scau402.system1.repository.IWmsCheckJadeDetailRepository;
import com.scau402.system1.repository.IWmsCheckOrderRepository;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 盘点单结算消费者
 */
@Slf4j
@Component
public class CheckBoundListener {
    // 实现出错处理
    @Autowired
    private IWmsCheckboundOrderMapper checkboundOrderMapper;
    @Autowired
    private Environment environment;

    @Autowired
    private IWmsCheckOrderRepository checkOrderRepo;
    @Autowired
    private IWmsCheckJadeDetailRepository checkJadeDetailRepo;

    int checkTimes1 = 0;
    long checkDeliveryTag1 = -1;

    /**
     * 对盘点单进行结算
     *
     * @param checkDTO
     */
    @RabbitListener(queues = "check.queue1")
    public void checkBoundClearingListener1(StopCheckDTO checkDTO, @Header(name = "amqp_deliveryTag") long deliveryTag) throws IOException {
        log.debug("盘点结算消费者一号接收到消息");
        try {
            checkClearing(checkDTO);
        } catch (Exception e) {
            // 获取重试次数
            int retryTimes = environment.getProperty("spring.rabbitmq.listener.simple.retry.max-attempts", Integer.class, 3);
            // 未到达重试次数上限
            if (checkTimes1 < retryTimes) {
                // 与上一条消息的tag一致，重试次数累加
                if (deliveryTag == this.checkDeliveryTag1) checkTimes1++;
                    // 不一致，重新计算重试次数
                else {
                    log.info("deliveryTag不同，重置");
                    log.info("原始tag: {},当前tag: {}", this.checkDeliveryTag1, deliveryTag);
                    this.checkDeliveryTag1 = deliveryTag;
                    checkTimes1 = 1;
                }
            }
            // 到达重试次数上限依旧失败
            if (checkTimes1 == retryTimes) {
                checkTimes1 = 0;
                this.checkDeliveryTag1 = -1;
                // 更新盘点单结算状态
                if (checkDTO != null && checkDTO.getWmsCheckBoundOrderPO() != null)
                    // 修改状态为结算失败
                    checkOrderRepo.updateToFailed(checkDTO.getWmsCheckBoundOrderPO().getId());
                else log.info("盘点单结算异常处理失败——空数据");
            }
            throw e;
        }
    }

    /**
     * 结算
     *
     * @param checkDTO dto
     */
    public void checkClearing(StopCheckDTO checkDTO) {
        boolean isSame = true;
        // 盘点单数据
        WmsCheckBoundOrderPO po = checkDTO.getWmsCheckBoundOrderPO();
        // 盘点单翡翠列表
        List<WmsCheckboundJadeDetailPO> jadeDetailPOList = checkDTO.getJadeDetailPOList();
        // 原数据Map
        Map<CheckKey, Long> oriCheckMap = jadeDetailPOList.stream().collect(
                Collectors.toMap(one -> new CheckKey(one.getBarcode(), one.getWarehouseId(), one.getStorageId())
                        , WmsCheckboundJadeDetailPO::getTotalNums)
        );
        // 前端统计结果
        List<WmsStopCheckDTO.CheckJade> checkJadeList = checkDTO.getDto().getCheckJadeList();
        for (WmsStopCheckDTO.CheckJade jade : checkJadeList) {
            CheckKey key = new CheckKey(jade.getBarcode(), jade.getWarehouseId(), jade.getStorageId());
            // 不存在数据 或 数据比对不一致
            if (!oriCheckMap.containsKey(key) || !oriCheckMap.get(key).equals(jade.getCheckNum())) {
                isSame = false;
                break;
            }
        }
        // 判断结果
        po.stopCheck(isSame);
        log.info("单号{} 是否一致： {}", po.getOrderCode(), isSame);
        // 入库
        checkboundOrderMapper.update(po, new QueryWrapper<WmsCheckBoundOrderPO>().eq("id", po.getId()));
        if (!checkDTO.getDto().getCheckJadeList().isEmpty()) checkJadeDetailRepo.stopCheck(checkDTO.getDto());
    }

    /**
     * 盘点MapKey
     */
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    private class CheckKey {
        /**
         * 翡翠条码
         */
        private String barcode;
        /**
         * 仓库id
         */
        private Long warehouseId;
        /**
         * 仓位id
         */
        private Long storageId;
    }
}
